package com.sz.common.core.system.service.impl;

import com.sz.common.base.exception.BizException;
import com.sz.common.base.fastdfs.FastDFSClientWrapper;
import com.sz.common.base.service.AbstractService;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.service.SysFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Function: SysFileServiceImpl <br>
 * Author: Charles <br>
 * Date: 2016-12-12 13:47:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class SysFileServiceImpl extends AbstractService implements SysFileService {
    @Autowired
    private FastDFSClientWrapper fastDFSClientWrapper;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.common.core.system.mapper.SysFileMapper";
    }

    /**
     * @param domainId
     * @param catalog
     * @param fileName
     * @param contentType
     * @param description
     * @param multipartFile
     * @return 文件可以访问到的完整路径
     */
    @Override
    public SysFile uploadFile(int domainId, String catalog, String fileName, String contentType,
                              String description, MultipartFile multipartFile) throws IOException {
        SysFile file = new SysFile();
        file.setCatalog(catalog);
        file.setFileName(fileName);
        file.setContentType(contentType);
        file.setDescription(description);
        file.setFileContent(null);
        String fullPath = fastDFSClientWrapper.uploadFile(multipartFile);
        file.setFileLocation("/" + fullPath);

        String fileId = generateFileId();
        file.setFileId(fileId);
        file.setFileSize(multipartFile.getSize());
        file.setHashCode(this.getFileHash(multipartFile.getBytes()));
        this.dao.save(this.getSqlName("insertSelective"), file);

        return file;
    }

    /**
     * @param fileId
     * @param catalog
     * @param fileName
     * @param contentType
     * @param description
     * @param isTempFile
     */
    @Override
    public void updateFileInfo(String fileId, String catalog, String fileName, String contentType,
                               String description, boolean isTempFile, int domainId) {
        SysFile file = new SysFile();
        file.setFileId(fileId);
        file.setCatalog(catalog);
        file.setFileName(fileName);
        file.setContentType(contentType);
        file.setIsTempFile(isTempFile);
        file.setDescription(description);
        file.setDomainId(domainId);
        List<SysFile> list = new ArrayList<>();
        list.add(file);
        this.updateFileInfo(list);
    }

    /**
     * @param files
     */
    @Override
    public void updateFileInfo(List<SysFile> files) {
        this.dao.batchUpdate(this.getSqlName("updateByPrimaryKeySelective"), files);
    }

    /**
     * @param fileId
     * @param content
     */
    public void updateFileContent(String fileId, byte[] content) {
        SysFile file = new SysFile();
        file.setFileId(fileId);
        file.setFileContent(content);
        file.setFileSize(content == null ? Long.valueOf(0) : Long.valueOf(content.length));
        file.setHashCode(this.getFileHash(content));
        this.dao.save(this.getSqlName("updateSelective"), file);
    }

    private String generateFileId() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "");
    }

    /**
     * 计算文件的md5hash
     *
     * @param content
     * @return
     */
    private String getFileHash(byte[] content) {
        if (content == null) {
            return "";
        }
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new BizException(e.getMessage());
        }
        md5.update(content, 0, content.length);
        return toHexString(md5.digest());
    }

    private String toHexString(byte[] b) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * @param fileId
     */
    @Override
    public void removeFile(String fileId) {
        this.dao.delete(getSqlName("deleteByFileId"), fileId);
    }

    /**
     * @param fileId
     * @return
     */
    @Override
    public SysFile getFileInfo(String fileId) {
        return (SysFile) this.dao.findForObject(getSqlName("selectByFileId"), fileId);
    }
    /**
     * @param fileIds fileIds
     * @return
     */
    @Override
    public List<SysFile> getFileInfos(List<String> fileIds) {
        return  this.dao.findForList(getSqlName("selectByFileIdsNoContent"), fileIds,SysFile.class);
    }

    /**
     * @param fileId
     * @return
     */
    @Override
    public SysFile getFileContent(String fileId) {
        return (SysFile) this.dao.findForObject(getSqlName("selectByFileIdWithContent"), fileId);
    }

    @Override
    public SysFile uploadFile(int domainId, String catalog, String fileName, String contentType, String description, String fullPath,Long fileSize) {
        SysFile file = new SysFile();
        file.setCatalog(catalog);
        file.setFileName(fileName);
        file.setContentType(contentType);
        file.setDescription(description);
        file.setFileContent(null);
        file.setFileLocation("/" + fullPath);

        String fileId = generateFileId();
        file.setFileId(fileId);
        file.setFileSize(fileSize);
        this.dao.save(this.getSqlName("insertSelective"), file);

        return file;
    }

    /**
     * 产品所有图片
     * @return
     */
    @Override
    public List<SysFile> allProductFiles(){
        return dao.findForList(getSqlName("allProductFiles"), null, SysFile.class);
    }

//    private static String getHash(String fileName, String hashType)
//            throws Exception {
//        InputStream fis = new FileInputStream(fileName);
//        byte buffer[] = new byte[1024];
//        MessageDigest md5 = MessageDigest.getInstance(hashType);
//        for(int numRead; (numRead = fis.read(buffer)) > 0;) {
//            md5.update(buffer, 0, numRead);
//        }
//        fis.close();
//        return "";//toHexString(md5.digest());
//    }
}
